package cn.yto.print.service.impl;

import cn.hutool.json.JSONUtil;
import cn.yto.print.config.CaffeineCacheConfig;
import cn.yto.print.config.PrintFutureContext;
import cn.yto.print.enums.PluginRegistryEnum;
import cn.yto.print.enums.PrintCmdEnum;
import cn.yto.print.enums.ResponseCodeEnum;
import cn.yto.print.model.dto.PrintCacheDTO;
import cn.yto.print.model.request.JingDongPrintRequest;
import cn.yto.print.model.request.PrintTaskRequest;
import cn.yto.print.model.response.JingDongPrintResponse;
import cn.yto.print.model.response.PrintTaskResponse;
import cn.yto.print.plugins.SocketSessionContext;
import cn.yto.print.service.PrintConsumerService;
import cn.yto.print.service.handle.ITextMessageFunction;
import cn.yto.print.service.handle.MessageHandler;
import cn.yto.print.utils.PrintTaskUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Component
public class JingDongMessageHandler extends MessageHandler {

    private SocketSessionContext socketSessionContext;

    @Override
    public void initialize() {
        socketSessionContext = new SocketSessionContext(PluginRegistryEnum.JD, createMessageHandler());
    }

    @Override
    public ITextMessageFunction createMessageHandler() {
        return (session, message) -> {
            CaffeineCacheConfig.getHeartCache().put(PluginRegistryEnum.JD.getCode(), 0);
            JingDongPrintResponse jdPrintResponse;
            try {
                jdPrintResponse = JSONUtil.toBean(message.getPayload(), JingDongPrintResponse.class);
            } catch (Exception e) {
                log.error("京东打印组件回执报文解析异常，报文将丢弃~", e);
                return;
            }

            if (null != jdPrintResponse.getCode() && "10005".equals(jdPrintResponse.getCode())) {
                return;
            }
            if (StringUtils.isEmpty(jdPrintResponse.getKey())) {
                return;
            }
            PrintCacheDTO printCache = CaffeineCacheConfig.getPrintCache().getIfPresent(jdPrintResponse.getKey());
            if (null == printCache) {
                log.error("京东打印任务 TaskID：{} 缓存不存在，报文将丢弃~", jdPrintResponse.getKey());
                return;
            }
            CaffeineCacheConfig.getPrintCache().invalidate(jdPrintResponse.getKey());
            PrintTaskResponse printTaskResponse = new PrintTaskResponse();
            printTaskResponse.setCmd(PrintCmdEnum.NOTIFY_PRINT_RESULT.getCmd());
            printTaskResponse.setTaskId(jdPrintResponse.getKey());
            printTaskResponse.setSessionId(printCache.getSessionId());
            printTaskResponse.setTemplateType(printCache.getTemplateType());
            String printStatus = jdPrintResponse.getSuccess() ? ResponseCodeEnum.SUCCESS.getStatus() : ResponseCodeEnum.FAILURE.getStatus();
            List<PrintTaskResponse.PrintStatus> printStatusList = new ArrayList<>();
            for (String documentId : printCache.getDocumentIds()) {
                PrintTaskResponse.PrintStatus failedStatus = new PrintTaskResponse.PrintStatus();
                failedStatus.setStatus(printStatus);
                failedStatus.setDocumentID(documentId);
                failedStatus.setMsg(jdPrintResponse.getMessage());
                printStatusList.add(failedStatus);
            }
            printTaskResponse.setPrintStatus(printStatusList);
            if (jdPrintResponse.getSuccess() && !CollectionUtils.isEmpty(jdPrintResponse.getDetailinfo().getErrors())) {
                for (JingDongPrintResponse.Error error : jdPrintResponse.getDetailinfo().getErrors()) {
                    if (error.getSeq() <= printCache.getDocumentIds().size()) {
                        PrintTaskResponse.PrintStatus newStatus = new PrintTaskResponse.PrintStatus();
                        newStatus.setStatus(ResponseCodeEnum.FAILURE.getStatus());
                        newStatus.setDocumentID(printCache.getDocumentIds().get(error.getSeq() - 1));
                        newStatus.setMsg(error.getMsg());
                        printTaskResponse.getPrintStatus().add(newStatus);
                    }
                }
            }
            CompletableFuture<PrintTaskResponse> future = PrintFutureContext.getResponseFuture(jdPrintResponse.getKey());
            if (null != future) {
                future.complete(printTaskResponse);
            } else {
                PrintConsumerService.handleTimeOutResponse(printTaskResponse);
            }
        };
    }

    @Override
    public JingDongPrintRequest buildPrintRequest(PrintTaskRequest pluginPrintParam) {
        JingDongPrintRequest printPluginRequest = new JingDongPrintRequest();
        printPluginRequest.setOrderType("PRINT");
        printPluginRequest.setKey(pluginPrintParam.getTaskId());
        printPluginRequest.setVersion("2");
        JingDongPrintRequest.Parameters parameters = new JingDongPrintRequest.Parameters();
        parameters.setPrintName(pluginPrintParam.getPrinter());
        List<JingDongPrintRequest.Content> contents = new ArrayList<>();
        for (PrintTaskRequest.Document document : pluginPrintParam.getDocuments()) {
            JingDongPrintRequest.Content content = new JingDongPrintRequest.Content();
            content.setTempUrl(document.getTemplateUrl());
            content.setPrintData(document.getPrintData());
            content.setCustomTempUrl(document.getCustomTempUrl());
            content.setCustomData(document.getCustomData());
            if (!CollectionUtils.isEmpty(document.getAddData())) {
                content.setAddData(document.getAddData());
            }
            contents.add(content);
        }
        parameters.setContents(contents);
        printPluginRequest.setParameters(parameters);
        return printPluginRequest;
    }

    @Override
    public CompletableFuture<PrintTaskResponse> processMessage(PrintTaskRequest printParam) {
        JingDongPrintRequest jingDongPrintRequest = buildPrintRequest(printParam);
        socketSessionContext.sendPrintRequest(jingDongPrintRequest);
        PrintTaskUtil.addPrintTaskCache(printParam);
        CompletableFuture<PrintTaskResponse> completableFuture = new CompletableFuture<>();
        PrintFutureContext.addResponseFuture(printParam.getTaskId(), completableFuture);
        return completableFuture;
    }

    @Override
    public SocketSessionContext getSocketContext() {
        return socketSessionContext;
    }

}
